package com.qq.weixin.service;

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.qq.weixin.enums.EventType;
import com.qq.weixin.enums.MsgType;
import com.qq.weixin.model.msg.BaseRcvMsg;
import com.qq.weixin.model.msg.RcvImageMsg;
import com.qq.weixin.model.msg.RcvLinkMsg;
import com.qq.weixin.model.msg.RcvLocationMsg;
import com.qq.weixin.model.msg.RcvShortVideoMsg;
import com.qq.weixin.model.msg.RcvTextMsg;
import com.qq.weixin.model.msg.RcvVideoMsg;
import com.qq.weixin.model.msg.RcvVoiceMsg;
import com.qq.weixin.model.msg.event.ClickEvent;
import com.qq.weixin.model.msg.event.LocationEvent;
import com.qq.weixin.model.msg.event.ScanEvent;
import com.qq.weixin.model.msg.event.SubscribeEvent;
import com.qq.weixin.model.msg.event.UnSubscribeEvent;
import com.qq.weixin.model.msg.event.ViewEvent;

public class RcvMessageService {
  Logger logger = Logger.getLogger(RcvMessageService.class);
  private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

  public BaseRcvMsg getRcvMsg(String xmltext) {
    try {
      DocumentBuilder db = dbf.newDocumentBuilder();
      StringReader sr = new StringReader(xmltext);
      InputSource is = new InputSource(sr);
      Document document = db.parse(is);
      Element root = document.getDocumentElement();

      NodeList n_msgtype = root.getElementsByTagName("MsgType");

      if (n_msgtype == null) {
        return null;
      }

      MsgType msgType = MsgType.convert(n_msgtype.item(0).getTextContent());
      if (msgType == MsgType.text) {
        return getRcvTextMsg(root);
      } else if (msgType == MsgType.image) {
        return getRcvImageMsg(root);
      } else if (msgType == MsgType.voice) {
        return getRcvVoiceMsg(root);
      } else if (msgType == MsgType.video) {
        return getRcvVideoMsg(root);
      } else if (msgType == MsgType.shortvideo) {
        return getRcvShortVideoMsg(root);
      } else if (msgType == MsgType.location) {
        return getRcvLocationMsg(root);
      } else if (msgType == MsgType.link) {
        return getRcvLinkMsg(root);
      } else if (msgType == MsgType.event) {
        NodeList n_eventtype = root.getElementsByTagName("Event");
        if (n_eventtype == null) {
          return null;
        }
        EventType eventType = EventType.convert(n_eventtype.item(0).getTextContent());
        if (eventType == EventType.subscribe) {
          return getSubscribeEvent(root);
        } else if (eventType == EventType.unsubscribe) {
          return getUnSubscribeEvent(root);
        } else if (eventType == EventType.SCAN) {
          return getScanEvent(root);
        } else if (eventType == EventType.LOCATION) {
          return getLocationEvent(root);
        } else if (eventType == EventType.CLICK) {
          return getClickEvent(root);
        } else if (eventType == EventType.VIEW) {
          return getViewEvent(root);
        }
      }

    } catch (Exception e) {
      logger.error("", e);
    }
    return null;
  }

  private void setCommonRcvMsg(BaseRcvMsg msg, Element root) {
    if (msg == null) {
      return;
    }
    if (root == null) {
      return;
    }
    NodeList n_tousername = root.getElementsByTagName("ToUserName");
    NodeList n_fromusername = root.getElementsByTagName("FromUserName");
    NodeList n_createtime = root.getElementsByTagName("CreateTime");
    NodeList n_msgid = root.getElementsByTagName("MsgId");

    msg.setToUser(n_tousername.item(0).getTextContent());
    msg.setFromUser(n_fromusername.item(0).getTextContent());
    msg.setCreateTime(Long.parseLong(n_createtime.item(0).getTextContent()));
    msg.setMsgId(n_msgid.item(0).getTextContent());
  }

  private RcvTextMsg getRcvTextMsg(Element root) {
    RcvTextMsg msg = new RcvTextMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_content = root.getElementsByTagName("Content");
    msg.setContent(n_content.item(0).getTextContent());
    return msg;
  }

  private RcvImageMsg getRcvImageMsg(Element root) {
    RcvImageMsg msg = new RcvImageMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_picurl = root.getElementsByTagName("PicUrl");
    NodeList n_mediaid = root.getElementsByTagName("MediaId");
    msg.setPicUrl(n_picurl.item(0).getTextContent());
    msg.setMediaId(n_mediaid.item(0).getTextContent());
    return msg;
  }

  private RcvVoiceMsg getRcvVoiceMsg(Element root) {
    RcvVoiceMsg msg = new RcvVoiceMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_mediaid = root.getElementsByTagName("MediaId");
    NodeList n_Format = root.getElementsByTagName("Format");
    msg.setMediaId(n_mediaid.item(0).getTextContent());
    msg.setFormat(n_Format.item(0).getTextContent());
    return msg;
  }

  private RcvVideoMsg getRcvVideoMsg(Element root) {
    RcvVideoMsg msg = new RcvVideoMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_mediaid = root.getElementsByTagName("MediaId");
    NodeList n_thumbmediaid = root.getElementsByTagName("ThumbMediaId");
    msg.setMediaId(n_mediaid.item(0).getTextContent());
    msg.setThumbMediaId(n_thumbmediaid.item(0).getTextContent());
    return msg;
  }

  private RcvShortVideoMsg getRcvShortVideoMsg(Element root) {
    RcvShortVideoMsg msg = new RcvShortVideoMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_mediaid = root.getElementsByTagName("MediaId");
    NodeList n_thumbmediaid = root.getElementsByTagName("ThumbMediaId");
    msg.setMediaId(n_mediaid.item(0).getTextContent());
    msg.setThumbMediaId(n_thumbmediaid.item(0).getTextContent());
    return msg;
  }

  private RcvLocationMsg getRcvLocationMsg(Element root) {
    RcvLocationMsg msg = new RcvLocationMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_location_x = root.getElementsByTagName("Location_X");
    NodeList n_location_y = root.getElementsByTagName("Location_Y");
    NodeList n_scale = root.getElementsByTagName("Scale");
    NodeList n_label = root.getElementsByTagName("Label");
    msg.setLocationX(n_location_x.item(0).getTextContent());
    msg.setLocationX(n_location_y.item(0).getTextContent());
    msg.setScale(Integer.parseInt(n_scale.item(0).getTextContent()));
    msg.setLabel(n_label.item(0).getTextContent());
    return msg;
  }

  private RcvLinkMsg getRcvLinkMsg(Element root) {
    RcvLinkMsg msg = new RcvLinkMsg();
    setCommonRcvMsg(msg, root);
    NodeList n_title = root.getElementsByTagName("Title");
    NodeList n_description = root.getElementsByTagName("Description");
    NodeList n_url = root.getElementsByTagName("Url");
    msg.setTitle(n_title.item(0).getTextContent());
    msg.setDescription(n_description.item(0).getTextContent());
    msg.setUrl(n_url.item(0).getTextContent());
    return msg;
  }

  private SubscribeEvent getSubscribeEvent(Element root) {
    SubscribeEvent msg = new SubscribeEvent();
    setCommonRcvMsg(msg, root);
    NodeList n_eventkey = root.getElementsByTagName("EventKey");
    NodeList n_ticket = root.getElementsByTagName("Ticket");
    if (n_eventkey != null) {
      msg.setEventKey(n_eventkey.item(0).getTextContent());
    }
    if (n_ticket != null) {
      msg.setTicket(n_ticket.item(0).getTextContent());
    }
    return msg;
  }

  private UnSubscribeEvent getUnSubscribeEvent(Element root) {
    UnSubscribeEvent msg = new UnSubscribeEvent();
    setCommonRcvMsg(msg, root);
    return msg;
  }

  private ScanEvent getScanEvent(Element root) {
    ScanEvent msg = new ScanEvent();
    setCommonRcvMsg(msg, root);
    NodeList n_eventkey = root.getElementsByTagName("EventKey");
    NodeList n_ticket = root.getElementsByTagName("Ticket");
    msg.setEventKey(n_eventkey.item(0).getTextContent());
    msg.setTicket(n_ticket.item(0).getTextContent());
    return msg;
  }

  private LocationEvent getLocationEvent(Element root) {
    LocationEvent msg = new LocationEvent();
    setCommonRcvMsg(msg, root);
    NodeList n_latitude = root.getElementsByTagName("Latitude");
    NodeList n_longitude = root.getElementsByTagName("Longitude");
    NodeList n_precision = root.getElementsByTagName("Precision");
    msg.setLatitude(n_latitude.item(0).getTextContent());
    msg.setLongitude(n_longitude.item(0).getTextContent());
    msg.setPrecision(n_precision.item(0).getTextContent());
    return msg;
  }

  private ClickEvent getClickEvent(Element root) {
    ClickEvent msg = new ClickEvent();
    setCommonRcvMsg(msg, root);
    NodeList n_eventkey = root.getElementsByTagName("EventKey");
    msg.setEventKey(n_eventkey.item(0).getTextContent());
    return msg;
  }

  private ViewEvent getViewEvent(Element root) {
    ViewEvent msg = new ViewEvent();
    setCommonRcvMsg(msg, root);
    NodeList n_eventkey = root.getElementsByTagName("EventKey");
    msg.setEventKey(n_eventkey.item(0).getTextContent());
    return msg;
  }
}
